﻿#region using
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using AwesomeTanks.Sources.Screens;
using AwesomeTanks.Sources.GameElements.TankElements;
using AwesomeTanks.Sources.GameElements.ShootElements;
using AwesomeTanks.Sources.GameElements.MapElements;
#endregion

namespace AwesomeTanks.Sources.Collision
{
    /// <summary>
    /// 
    /// </summary>
    public class CollisionManager
    {
        #region Methods
        /// <summary>
        /// Textures the to 2D array.
        /// </summary>
        /// <param name="texture">The texture.</param>
        /// <param name="sourceRectangle">The source rectangle.</param>
        /// <returns></returns>
        public static Color[,] TextureTo2DArray(Texture2D texture, Rectangle sourceRectangle)
        {
            Color[] colors1D = new Color[texture.Width * texture.Height];
            texture.GetData(colors1D);

            int totalX = sourceRectangle.X + sourceRectangle.Width;
            int totalY = sourceRectangle.Y + sourceRectangle.Height;
            Color[,] colors2D = new Color[sourceRectangle.Width, sourceRectangle.Height];
            for (int x = sourceRectangle.X; x < totalX; x++)
            {

                for (int y = sourceRectangle.Y; y < totalY; y++)
                {
                    int i = x - sourceRectangle.X;
                    int j = y - sourceRectangle.Y;
                    colors2D[i, j] = colors1D[x + y * texture.Width];
                }
            }
            return colors2D;
        }

        /// <summary>
        /// Textures collision.
        /// </summary>
        /// <param name="tex1">The tex1.</param>
        /// <param name="mat1">The mat1.</param>
        /// <param name="tex2">The tex2.</param>
        /// <param name="mat2">The mat2.</param>
        /// <returns></returns>
        public static Vector2 TexturesCollide(Color[,] tex1, Matrix mat1, Color[,] tex2, Matrix mat2)
        {
            Matrix mat1to2 = mat1 * Matrix.Invert(mat2);
            int width1 = tex1.GetLength(0);
            int height1 = tex1.GetLength(1);
            int width2 = tex2.GetLength(0);
            int height2 = tex2.GetLength(1);

            for (int x1 = 0; x1 < width1; x1++)
            {
                for (int y1 = 0; y1 < height1; y1++)
                {
                    Vector2 pos1 = new Vector2(x1, y1);
                    Vector2 pos2 = Vector2.Transform(pos1, mat1to2);

                    int x2 = (int)pos2.X;
                    int y2 = (int)pos2.Y;
                    if ((x2 >= 0) && (x2 < width2))
                    {
                        if ((y2 >= 0) && (y2 < height2))
                        {
                            if (tex1[x1, y1].A > 0)
                            {
                                if (tex2[x2, y2].A > 0)
                                {
                                    Vector2 screenPos = Vector2.Transform(pos1, mat1);
                                    return screenPos;
                                }
                            }
                        }
                    }
                }
            }

            return new Vector2(-1, -1);
        }

        /// <summary>
        /// Checks the collisions.
        /// </summary>
        /// <param name="gameTime">The game time.</param>
        public static void CheckCollisions(GameTime gameTime)
        {
            for (int i = 0; i < GameplayScreen.listTank.Count - 1; i++)
            {
                Tank tank1 = GameplayScreen.listTank.ElementAt(i);
                for (int j = i + 1; j < GameplayScreen.listTank.Count; j++)
                {
                    Tank tank2 = GameplayScreen.listTank.ElementAt(j);
                    TankCollisions.TankCollision(tank1, tank2, gameTime);
                }
            }

            foreach (Tank tank in GameplayScreen.listTank) {
                foreach (Wall wall in GameplayScreen.map.ListWall)
               {
                   TankCollisions.WallCollision(tank, wall, gameTime);
               }
            }

            foreach (Shoot shoot in ShootManager.ShotList)
            {
                foreach (Tank tank in GameplayScreen.listTank)
                {
                    ShootCollisions.TankCollision(shoot, tank, gameTime);
                }
                foreach (Wall wall in GameplayScreen.map.ListWall)
                {
                    ShootCollisions.WallCollision(shoot, wall);
                }
            }
            ShootManager.ShotList = ShootManager.ShotList.Where(x => !x.ToRemove).ToList();
        }
        #endregion
    }
}
